module service.GroupService;

import repository;
import model;
import client.MsgServerClient;
import msgtrans;
import hunt.logging;
import message.Constants;
import message.MsgDefine;
import std.conv : to;
import core.stdc.time;
import bootstrap.DatabaseBootstrap;

import hunt.framework;

class GroupService {

    static int addGroup(CreateGroupREQ req,message.MsgDefine.User[] users)
    {
            auto em = defaultEntityManager();
            em.getTransaction().begin();
            GroupRepository repo = new GroupRepository;
            int id =    repo.addGroup(req,em);
            foreach(message.MsgDefine.User u ; users)
            {
                GroupService.addGroupUser(u.id, id, u.nickname,em);
            }
            em.getTransaction().commit();
            em.close();
            return id;
    }

    static void groupInvite(InviteGroup req ,string destination)
    {
            auto em = defaultEntityManager();
            em.getTransaction().begin();
            GroupService.addGroupUser(destination, to!int(req.groupId), req.aliasName, em);
            em.getTransaction().commit();
            em.close();
    }

    static void addGroupUser(string userId, int groupId, string nickname ,EntityManager em)
    {
            GroupUserRepository repo = new GroupUserRepository;
            repo.addGroupUser(userId,groupId,nickname,em);
    }

    static void addGroupApply(ApplyGroup req,uint type)
    {
            GroupApplyRepository repo = new GroupApplyRepository;
            repo.addGroupApply(req,type);
    }

    static void updateGroupApplyStatus(string groupId, string fromId, string toId, bool succeeded)
    {
            GroupApplyRepository repo = new GroupApplyRepository;
            repo.updateGroupApply(groupId, fromId, toId, succeeded);
    }

    static void setValidation(uint validation, string groupId, string manager)
    {
             GroupRepository repo = new GroupRepository;
             repo.setValidation(validation,groupId,manager);
    }

    static void setGroupName(string groupId, string groupName)
    {
            GroupRepository repo = new GroupRepository;
            repo.setGroupName(groupId,groupName);
    }

    static JoinGroup selectGroupInfo(string groupId, string fromId)
    {
        import message.MsgDefine;
        auto userRepo = new UserRepository();
        auto groupRepo = new GroupRepository();
        auto groupUserRepo = new GroupUserRepository();
        User[] members;
        ChatGroup groupInfo = groupRepo.findByUid(to!int(groupId));

        GroupUser[] users = groupUserRepo.findAllByID(to!int(groupId));
        foreach(GroupUser u ; users)
        {
            auto user = userRepo.findById(u.userId);
            if(user is null)
            {
                logWarningf("not this userinfo %d" , u.userId);
                continue;
            }
            auto resUser = toUser(user);
            members ~= resUser;
        }

        JoinGroup res = new JoinGroup();
        res.groupId = groupId;
        res.aliasName = groupInfo.aliasName;
        res.validation = groupInfo.validation;
        res.notice = groupInfo.notice;
        res.destination = fromId;
        res.member = members;
        return res;
    }

    static void deleteGroupUser(string userId, string groupId)
    {
        auto groupUserRepo = new GroupUserRepository();
        bool changeManger = false;
        bool deleteGroup = false;
        uint newManagerId = 0;
        auto em = defaultEntityManager();

        if(isCreator(userId, groupId))
        {
             changeManger = true;
             newManagerId = selectManager(groupId, userId);
             if(newManagerId == 0)
             {
                deleteGroup = true;
             }
        }

        em.getTransaction().begin();

        if (changeManger)
        {
            if(deleteGroup)
            {
                GroupService.deleteGroup(groupId, em);
            }
            else
            {
                GroupService.changeManager(groupId, userId, em);
            }
        }

        groupUserRepo.deleteGroupUser(groupId, userId, em);

        em.getTransaction().commit();
        em.close();
    }

    static void deleteGroup(string groupId, EntityManager em)
    {
        auto groupRep = new GroupRepository;
        groupRep.deleteGroup(groupId, em);
    }

    static void changeManager(string groupId, string userId, EntityManager em)
    {
        auto groupRep = new GroupRepository;
        groupRep.changeManager(groupId, userId, em);
    }

    static void cancelGroup(string fromId, string groupId)
    {
        //if (!isCreator(fromId, groupId))
        //{
        //        logErrorf("user %s is not group creator %s", fromId, groupId);
        //        return;
        //}
        //auto groupUserRepo = new GroupUserRepository;
        //auto groupRepo = new GroupRepository;
        //groupUserRepo.deleteAllGroupUser(groupId);
        //groupRepo.deleteGroup(groupId);
    }

    static bool isCreator(string fromId, string groupId)
    {
        auto groupRepo = new GroupRepository;
        return groupRepo.isCreator(fromId, groupId);
    }

    static uint selectManager(string groupId, string oldManagerId)
    {
        auto groupRepo = new GroupUserRepository;
        return groupRepo.selectManager(groupId, oldManagerId);
    }

    static bool needValidation(string groupId, string userId , out string manager)
    {
         auto groupRepo = new GroupRepository;
         return groupRepo.needValidation(groupId, userId, manager);
    }

    static bool isExist(string uid , string groupId)
    {
        auto groupRepo = new GroupUserRepository;
        return groupRepo.isExist(to!uint(uid),to!uint(groupId));
    }

    static void updateGroupInfo(UpdateGroupInfo req)
    {
        if (isCreator(req.fromId,req.groupId))
        {
            auto groupRepo = new GroupRepository;
            groupRepo.updateGroupInfo(req);
        }
        return;
    }

    static GroupInfo[] getAllGroupMember(string userId)
    {
        GroupInfo[] rt;
        GroupUserRepository groupUserRepo = new GroupUserRepository;
        GroupRepository groupRepo = new GroupRepository;
        GroupUser[] gps = groupUserRepo.findAllByUserId(to!uint(userId));
        foreach(GroupUser g ; gps)
        {
            GroupInfo ct = new GroupInfo;
            ct.groupId = to!int(g.groupId);
            auto groupInfo = groupRepo.findByUid(ct.groupId);
            ct.groupName = groupInfo.aliasName;
            ct.validation = groupInfo.validation;
            GroupUser[] mbs = groupUserRepo.findAllByID(ct.groupId);
            foreach(GroupUser m ; mbs)
            {
                ct.memberId ~= to!int(m.userId);
            }
            rt ~= ct;
        }
        return rt;
    }
}

